#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "VertexList.h"
#include "GL/glut.h"
VertexList::VertexList()
{
	head = NULL;
	tail = NULL;
	minVertices = 0;
	maxVertices = -1;
}
VertexList::VertexList(Vertex * headVertex)
{
	head = new List<Vertex>(headVertex, NULL);
	tail = head;
	minVertices = 0;
	maxVertices = -1;
}
VertexList::~VertexList()
{
	printf("deleting vector list\n");
	List<Vertex> * search = head;
	int i = 0;
	while(search)
	{
		printf("vector number %d\n",i);
		i++;
		search = search->RemoveList();
	}
	head = NULL;
	printf("done deleting vectors\n");
}
void VertexList::SetMin(int min)
{
	this->minVertices = min;
}
void VertexList::SetMax(int max)
{
	this->maxVertices = max;
}
List<Vertex> * VertexList::Add(Vertex * payload)
{
	if(GetLength() == maxVertices)
		return head;
		
	head = new List<Vertex>(payload, head);
	if(tail == NULL)
		tail = head;
	return head;
}
void VertexList::AddBefore(Vertex * payload, Vertex * after)
{
	if(GetLength() == maxVertices)
		return;
		 
	List<Vertex> * search = head;
	while(search)
	{
		if(search->payload)
		{
			if(search->payload == after)
			{
				List<Vertex> * temp = search->prev;
				List<Vertex> * newPoint = new List<Vertex>(payload, search);
				if(temp)
				{
					newPoint->prev = temp;	
					temp->next = newPoint;
				}
				else
				{
					head = newPoint;
				}	
				break;
			}
		}
		search = search->next;
	}
}
void VertexList::ClearList()
{
	List<Vertex> * search = head;
	while(search)
	{
		search = search->RemoveList();
	}
	head = NULL;
	tail = NULL;
}
void VertexList::Remove(Vertex point)
{
	if(GetLength() == minVertices)
		return;
		
	List<Vertex> * search = head;
	while(search)
	{
		if(search->payload && (search->payload->GetPosition() | point.GetPosition()) < 0.001)
		{
			if(search == head)
			{
				head = search->next;
			}
			else if(search == tail)
			{
				tail = search->prev;
			}
			search = search->Remove();
			break;
		}
		else
			search = search->next;
	}	
}

void VertexList::Remove(Vertex * point)
{
	if(GetLength() < minVertices)
		return; 
		
	List<Vertex> * search = head;
	while(search)
	{
		if(search->payload && search->payload ==  point)
		{
			if(search == head)
			{
				head = search->next;
			}
			else if(search == tail)
			{
				tail = search->prev;
			}
			search = search->Remove();
			break;
		}
		else
			search = search->next;
	}	
}

void VertexList::HoverCheck(Mouse * mouse)
{
	List<Vertex> * search = head;
	while(search)
	{
		if(search->payload)
		{
			search->payload->HoverCheck(mouse);
			List<Vertex> * next = search->next;
			if(next)
			{
				//is the mouse near the line?
				Vector2D mouseWorldPos = mouse->GetPosition();
				Vector2D leftPoint = search->payload->GetPosition();
				Vector2D rightPoint = next->payload->GetPosition();
				Vector2D closestPoint = Vector2D::ClosestPointOnSegment(leftPoint, rightPoint, mouseWorldPos);	
				if((closestPoint | mouseWorldPos) < 1)
				{
					search->payload->activeSegment = true;
					//break;
				}
				else
					search->payload->activeSegment = false;
			}
		}
		search = search->next;
	}	
}
void VertexList::GetHoverSegment(Mouse * mouse, Vertex ** left, Vertex ** right)
{
	List<Vertex> * search = head;
	while(search && search->next)
	{
		if(search->payload)
		{
			if(search->payload->activeSegment)
			{
				*left = search->payload;
				*right = search->next->payload;
			}
		}
		search = search->next;
	}
}
Vertex * VertexList::GetHoverVertex(Mouse * mouse)
{
	List<Vertex> * search = head;
	while(search)
	{
		if(search->payload)
		{
			if((search->payload->GetPosition() | mouse->GetPosition()) < 0.02)
				return search->payload;
		}
		search = search->next;
	}	
	return NULL;
}
char * VertexList::GetRelativeTag(Vector2D relativePosition)
{
	List<Vertex> * search = tail;
	
	int length = 0;
	char * tag = NULL;
	
	while(search)
	{
		if(search->payload)
		{
			char * point = search->payload->GetRelativeTag(relativePosition);
			int commaSpace = 0;
			if(search->prev)
				commaSpace = 1;
			tag = (char *)realloc(tag, (length + strlen(point) + 1 + commaSpace) * sizeof(char));
			memcpy(tag+length,point, strlen(point)+1);
	
			if(commaSpace)
			{
				int len = strlen(tag);
				tag[len] = ',';
				tag[len+1]='\0';
			}
			length += strlen(point)+commaSpace;
			delete point;
		}
		search = search->prev;
	}
	return tag;
}
char * VertexList::GetBackwardsTag()
{
	List<Vertex> * search = head;
	
	int length = 0;
	char * tag = NULL;
	
	while(search)
	{
		if(search->payload)
		{
			char * point = search->payload->GetTag();
			int commaSpace = 0;
			if(search->next)
				commaSpace = 1;
			tag = (char *)realloc(tag, (length + strlen(point) + 1 + commaSpace) * sizeof(char));
			memcpy(tag+length,point, strlen(point)+1);
	
			if(commaSpace)
			{
				int len = strlen(tag);
				tag[len] = ',';
				tag[len+1]='\0';
			}
			length += strlen(point)+commaSpace;
			delete point;
		}
		search = search->next;
	}
	return tag;
}
char * VertexList::GetTag()
{
	List<Vertex> * search = tail;
	
	int length = 0;
	char * tag = NULL;
	
	while(search)
	{
		if(search->payload)
		{
			char * point = search->payload->GetTag();
			int commaSpace = 0;
			if(search->prev)
				commaSpace = 1;
			tag = (char *)realloc(tag, (length + strlen(point) + 1 + commaSpace) * sizeof(char));
			memcpy(tag+length,point, strlen(point)+1);
	
			if(commaSpace)
			{
				int len = strlen(tag);
				tag[len] = ',';
				tag[len+1]='\0';
			}
			length += strlen(point)+commaSpace;
			delete point;
		}
		search = search->prev;
	}
	return tag;
}
void VertexList::Draw()
{
	List<Vertex> * search = head;
	
	while(search)
	{
		if(search->payload)
		{
			search->payload->Draw();
		}
		search = search->next;
	}
	search = head;
	glColor3f(0,1,0);
	glBegin(GL_LINES);	
	Vector2D lastPos = search->payload->GetPosition();
	search = search->next;
	while(search)
	{
		if(search->payload)
		{
			Vector2D pos = search->payload->GetPosition();
			glVertex2f(lastPos.x, lastPos.y);
			glVertex2f(lastPos.x, pos.y);
			
			glVertex2f(lastPos.x, pos.y);
			glVertex2f(pos.x, pos.y);
			
			glVertex2f(pos.x, pos.y);
			glVertex2f(pos.x, lastPos.y);
			
			glVertex2f(pos.x, lastPos.y);
			glVertex2f(lastPos.x, lastPos.y);
			lastPos = pos;
		}
		search = search->next;
	}
	glEnd();
}
int VertexList::GetLength()
{
	List<Vertex> * search = head;
	int i =0;
	while(search)
	{
		i++;
		search = search->next;
	}
	return i;
}

